<template>
	<div class="main">
		<view class="voice">
			<view class="voice-body">
				<view class="voice-body-line" 
					v-if="voicelist.length>0"
					v-for="item,index in voicelist"
					:key="index"
				>
					<view class="voice-body-piece"  
						:style="{width:item.width+'vw'}" 
					>
						<view class="recordicon" @click="voiceplay(item.idx)"></view>
						<view class="" @click="voiceplay(item.idx)">{{item.time}}″</view>
						<view class=""></view>
					</view>
					<view class=""></view>
					<view class="voice-delete" @click="voicedelete(item.idx)"></view>
				</view>
			</view>
			<view class="voice-button"
			    @touchstart="handleTouchStart"
			    @touchend="handleTouchEnd"
			>
			    <view class=""></view>
				<view class="microphoneicon"></view>
				<view class="voice-button-text">{{recordbtn}}</view>
				<view class=""></view>
			</view>
		</view>
	    <!-- <div class="mainBox">
			
	    </div> -->
	
	    <!-- <div class="mainBox">
	        <div style="height:100px;width:300px;border:1px solid #ccc;box-sizing: border-box;display:inline-block;vertical-align:bottom" class="ctrlProcessWave"></div>
	        <div style="height:40px;width:300px;display:inline-block;background:#999;position:relative;vertical-align:bottom">
	            <div class="ctrlProcessX" style="height:40px;background:#0B1;position:absolute;" :style="{width:powerLevel+'%'}"></div>
	            <div class="ctrlProcessT" style="padding-left:50px; line-height:40px; position: relative;">{{ duration+"/"+powerLevel }}</div>
	        </div>
	    </div> -->
	    
	    <!-- <div class="mainBox">
	        <audio ref="LogAudioPlayer" style="width:100%"></audio>
	
	        <div class="mainLog">
	            <div v-for="obj in logs" :key="obj.idx">
	                <div :style="{color:obj.color==1?'red':obj.color==2?'green':obj.color}">
	                    <span v-once>[{{ getTime() }}]</span><span v-html="obj.msg"/>
	                    
	                    <template v-if="obj.res">
	                        {{ intp(obj.res.rec.set.bitRate,3) }}kbps
	                        {{ intp(obj.res.rec.set.sampleRate,5) }}hz
	                        编码{{ intp(obj.res.blob.size,6) }}b
	                        [{{ obj.res.rec.set.type }}]{{ intp(obj.res.duration,6) }}ms 
	                        
	                        <button @click="recdown(obj.idx)">下载</button>
	                        <button @click="recplay(obj.idx)">播放</button>
	
	                        <span v-html="obj.playMsg"></span>
	                        <span v-if="obj.down">
	                            <span style="color:red">{{ obj.down }}</span>
	                            
	                            没弹下载？试一下链接或复制文本<button @click="recdown64(obj.idx)">生成Base64文本</button>
	
	                            <textarea v-if="obj.down64Val" v-model="obj.down64Val"></textarea>
	                        </span>
	                    </template>
	                </div>
	            </div>
	        </div>
	    </div> -->
	
	    <div v-if="recOpenDialogShow" style="z-index:99999;width:100%;height:100%;top:0;left:0;position:fixed;background:rgba(0,0,0,0.3);">
	        <div style="display:flex;height:100%;align-items:center;">
	            <div style="flex:1;"></div>
	            <div style="width:240px;background:#fff;padding:15px 20px;border-radius: 10px;">
	                <div style="padding-bottom:10px;">录音功能需要麦克风权限，请允许；如果未看到任何请求，请点击忽略~</div>
	                <div style="text-align:center;"><a @click="waitDialogClick" style="color:#0B1">忽略</a></div>
	            </div>
	            <div style="flex:1;"></div>
	        </div>
	    </div>
	
	    <slot name="bottom"></slot>
	</div>
</template>

<script>
	import { getCommonUploads} from "@/api/index";
module.exports={
    data(){
        return {
            Rec:Recorder
            
            ,type:"mp3"
            ,bitRate:16
            ,sampleRate:16000

            ,rec:0
            ,duration:0
            ,powerLevel:0

            ,recOpenDialogShow:0
            ,logs:[]
			
			,recordbtn: '按住此处说话',
			voicelist: [],
			// innerAudioContext: null,
        }
    }
	,created() {
	   this.Initialize()
	}
    ,methods:{
		Initialize(){
			this.$store.state.user.voicelist=[]
			this.recOpen()
		},
		voiceplay(idx){
			var o=this.logs[this.logs.length-idx-1];
			o.play=(o.play||0)+1;
			console.log("o",o)
			console.log("(window.URL||webkitURL).createObjectURL(o.res.blob)",(window.URL||webkitURL).createObjectURL(o.res.blob))
			this.innerAudioContext = uni.createInnerAudioContext();
			
			this.innerAudioContext.src =  (window.URL||webkitURL).createObjectURL(o.res.blob); // 本地音乐文件绝对路径
			this.innerAudioContext.play();
		},
		voicedelete(idx){
			let list = []
			for(let i in this.voicelist){
				if(idx!=this.voicelist[i].idx){
					list.push(this.voicelist[i])
				}
			}
			this.voicelist = list
		},
		handleTouchStart(){
			this.recordbtn = '松开停止录音'
			this.recStart()
		},
		handleTouchEnd(){
			this.recordbtn = '按住此处说话'
			this.recStop()
		},
		dealvoicelist(){
			let _this= this
			let data = this.logs[0]
			let time = (data.res.duration-data.res.duration%1000)/1000
			let vdata = data.res.blob
			let base64 = ''
			let reader = new FileReader();
			reader.onloadend = async function() {
				base64 = reader.result
				_this.voicelist.push({
					"idx": data.idx,
					"duration": data.res.duration,
					"time": time,
					"width": time+20,
					"blob": data.res.blob,
					"base64": base64,
					"url": '',
				})
				// console.log("this.voicelistdealvoicelist",_this.voicelist)
				_this.$store.state.user.voicelist = _this.voicelist
			}
			reader.readAsDataURL(vdata);
		},
		convertbase64(data){
			let result = ''
			let reader = new FileReader();
			reader.onloadend = function() {
			    result = reader.result;
			};
			reader.readAsDataURL(data);
			console.log("convertbase64",result)
			return result
		},
        recOpen:function(){
            var This=this;
            var rec=this.rec=Recorder({
                type:This.type
                ,bitRate:This.bitRate
                ,sampleRate:This.sampleRate
                ,onProcess:function(buffers,powerLevel,duration,sampleRate){
                    This.duration=duration;
                    This.powerLevel=powerLevel;

                    // This.wave.input(buffers[buffers.length-1],powerLevel,sampleRate);
                }
            });

            // This.dialogInt=setTimeout(function(){//定时8秒后打开弹窗，用于监测浏览器没有发起权限请求的情况
            //     This.showDialog();
            // },8000);

            rec.open(function(){
                This.dialogCancel();
                This.reclog("已打开:"+This.type+" "+This.sampleRate+"hz "+This.bitRate+"kbps",2);
                
                // This.wave=Recorder.WaveView({elem:".ctrlProcessWave"});
            },function(msg,isUserNotAllow){
                This.dialogCancel();
                This.reclog((isUserNotAllow?"UserNotAllow，":"")+"打开失败："+msg,1);
            });

            This.waitDialogClickFn=function(){
                This.dialogCancel();
                This.reclog("打开失败：权限请求被忽略，用户主动点击的弹窗",1);
            };
        }
		,recClose:function(){
            var rec=this.rec;
            this.rec=null;
			if(rec){
				rec.close();
				this.reclog("已关闭");
			}else{
				this.reclog("未打开录音",1);
			};
		}
        ,recStart:function(){
            if(!this.rec||!Recorder.IsOpen()){
                this.reclog("未打开录音",1);
                return;
            }
            this.rec.start();

            var set=this.rec.set;
            this.reclog("录制中："+set.type+" "+set.sampleRate+"hz "+set.bitRate+"kbps");
			setTimeout(this.handleTouchEnd,60000)
        }
		,recPause:function(){
			if(this.rec&&Recorder.IsOpen()){
				this.rec.pause();
			}else{
				this.reclog("未打开录音",1);
			};
		}
		,recResume:function(){
			if(this.rec&&Recorder.IsOpen()){
				this.rec.resume();
			}else{
				this.reclog("未打开录音",1);
			};
		}
        ,recStop:function(){
            if(!(this.rec&&Recorder.IsOpen())){
                This.reclog("未打开录音",1);
                return;
            }
			
            var This=this;
            var rec=This.rec;
            rec.stop(function(blob,duration){
                This.reclog("已录制:","",{
                    blob:blob
                    ,duration:duration
                    ,rec:rec
                });
				This.dealvoicelist()
            },function(s){
                This.reclog("录音失败："+s,1);
            });
        }
		,recPlayLast:function(){
			if(!this.recLogLast){
				this.reclog("请先录音，然后停止后再播放",1);
				return;
			};
			this.recplay(this.recLogLast.idx);
		}
		,recUploadLast:function(){
			if(!this.recLogLast){
				this.reclog("请先录音，然后停止后再上传",1);
				return;
			};
			var This=this;
			var blob=this.recLogLast.res.blob;
			
			//本例子假设使用原始XMLHttpRequest请求方式，实际使用中自行调整为自己的请求方式
			//录音结束时拿到了blob文件对象，可以用FileReader读取出内容，或者用FormData上传
			var api="https://xx.xx/test_request";
			var onreadystatechange=function(title){
				return function(){
					if(xhr.readyState==4){
						if(xhr.status==200){
							This.reclog(title+"上传成功",2);
						}else{
							This.reclog(title+"没有完成上传，演示上传地址无需关注上传结果，只要浏览器控制台内Network面板内看到的请求数据结构是预期的就ok了。", "#d8c1a0");
							
							console.error(title+"上传失败",xhr.status,xhr.responseText);
						};
					};
				};
			};
			This.reclog("开始上传到"+api+"，请求稍后...","#f60");

			/***方式一：将blob文件转成base64纯文本编码，使用普通application/x-www-form-urlencoded表单上传***/
			var reader=new FileReader();
			reader.onloadend=function(){
				var postData="";
				postData+="mime="+encodeURIComponent(blob.type);//告诉后端，这个录音是什么格式的，可能前后端都固定的mp3可以不用写
				postData+="&upfile_b64="+encodeURIComponent((/.+;\s*base64\s*,\s*(.+)$/i.exec(reader.result)||[])[1]) //录音文件内容，后端进行base64解码成二进制
				//...其他表单参数
				
				var xhr=new XMLHttpRequest();
				xhr.open("POST", api);
				xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
				xhr.onreadystatechange=onreadystatechange("上传方式一【Base64】");
				xhr.send(postData);
			};
			reader.readAsDataURL(blob);

			/***方式二：使用FormData用multipart/form-data表单上传文件***/
			var form=new FormData();
			form.append("upfile",blob,"recorder.mp3"); //和普通form表单并无二致，后端接收到upfile参数的文件，文件名为recorder.mp3
			//...其他表单参数
			
			var xhr=new XMLHttpRequest();
			xhr.open("POST", api);
			xhr.onreadystatechange=onreadystatechange("上传方式二【FormData】");
			xhr.send(form);
		}
        ,reclog:function(msg,color,res){
			var obj={
                idx:this.logs.length
                ,msg:msg
                ,color:color
                ,res:res

                ,playMsg:""
                ,down:0
                ,down64Val:""
            };
			if(res&&res.blob){
				this.recLogLast=obj;
			};
            this.logs.splice(0,0,obj);
        }
        ,recplay:function(idx){
            var This=this;
            var o=this.logs[this.logs.length-idx-1];
            o.play=(o.play||0)+1;
            var logmsg=function(msg){
                o.playMsg='<span style="color:green">'+o.play+'</span> '+This.getTime()+" "+msg;
            };
            logmsg("");

            var audio=this.$refs.LogAudioPlayer;
            audio.controls=true;
            if(!(audio.ended || audio.paused)){
                audio.pause();
            };
            audio.onerror=function(e){
                logmsg('<span style="color:red">播放失败['+audio.error.code+']'+audio.error.message+'</span>');
            };
            audio.src=(window.URL||webkitURL).createObjectURL(o.res.blob);
            audio.play();
        }
        ,recdown:function(idx){
            var This=this;
            var o=this.logs[this.logs.length-idx-1];
            o.down=(o.down||0)+1;

            o=o.res;
            var name="rec-"+o.duration+"ms-"+(o.rec.set.bitRate||"-")+"kbps-"+(o.rec.set.sampleRate||"-")+"hz."+(o.rec.set.type||(/\w+$/.exec(o.blob.type)||[])[0]||"unknown");
            var downA=document.createElement("A");
            downA.href=(window.URL||webkitURL).createObjectURL(o.blob);
            downA.download=name;
            downA.click();
        }
        ,recdown64:function(idx){
            var This=this;
            var o=this.logs[this.logs.length-idx-1];
            var reader = new FileReader();
            reader.onloadend = function() {
                o.down64Val=reader.result;
            };
            reader.readAsDataURL(o.res.blob);
        }
        ,getTime:function(){
            var now=new Date();
            var t=("0"+now.getHours()).substr(-2)
                +":"+("0"+now.getMinutes()).substr(-2)
                +":"+("0"+now.getSeconds()).substr(-2);
            return t;
        }
        ,intp:function(s,len){
            s=s==null?"-":s+"";
            if(s.length>=len)return s;
            return ("_______"+s).substr(-len);
        }


        ,showDialog:function(){
            //我们可以选择性的弹一个对话框：为了防止移动端浏览器存在第三种情况：用户忽略，并且（或者国产系统UC系）浏览器没有任何回调
            if(!/mobile/i.test(navigator.userAgent)){
                return;//只在移动端开启没有权限请求的检测
            };
            this.recOpenDialogShow=1;
        }
        ,dialogCancel:function(){
            clearTimeout(this.dialogInt);
            this.recOpenDialogShow=0;
        }
        ,waitDialogClick:function(){
            this.dialogCancel();
            this.waitDialogClickFn();
        }
    },
	beforeDestroy(){
		this.recClose()
	}
}
</script>
<style>
	.voice{
		padding: 2.5vw;
		width: 92vw;
		max-height: 47.5vw;
		display: grid;
		justify-items: center;
		align-items: center;
		grid-row-gap: 2.5vw;
		grid-template-rows: auto auto;
		background: #ffffff;
	}
	.voice-body{
		width:87vw;
		max-height: 30vw;
		overflow: auto;
	}
	.voice-body-line{
		margin: 2vw 0;
		width: 87vw;
		height: 10vw;
		display: grid;
		justify-items: start;
		align-items: center;
		grid-template-columns: auto 1fr auto;
	}
	.voice-body-piece{
		padding: 0 2vw;
		height: 10vw;
		border-radius: 5vw;
		background: #DCEDFF;
		display: grid;
		justify-items: start;
		align-items: center;
		grid-column-gap: 2vw;
		grid-template-columns: auto auto 1fr;
		cursor: pointer;
	}
	.voice-delete{
		float: right;
		width: 3vw;
		height: 3vw;
		background: url(../static/index/delete.png);
		background-size: 100% 100%;
	}
	.recordicon{
		width: 5vw;
		height: 5vw;
		background: url(../static/index/record.png);
		background-size: 100% 100%;
	}
	.microphoneicon{
		margin: 1vw 0 0 0;
		width: 5vw;
		height: 5vw;
		background: url(../static/index/microphone.png);
		background-size: 100% 100%;
	}
	.voice-button{
		width: 87vw;
		height: 10vw;
		border-radius: 5vw;
		display: grid;
		justify-items: center;
		align-items: center;
		grid-row-gap: 2vw;
		grid-template-columns: 1fr auto auto auto 1fr;
		/* font-size: 4vw; */
		color: #ffffff;
		background: #1492FF;
		cursor: pointer;
	}
	.voice-button-text{
		display: grid;
		justify-items: center;
		align-items: center;
	}
</style>